package com.muyu.vehicle.service.impl;

import java.util.*;

import com.github.pagehelper.Page;
import com.muyu.vehicle.config.Config;
import com.muyu.vehicle.domain.es.InfoEs;
import com.muyu.vehicle.domain.vo.IndexVehicleData;
import com.muyu.vehicle.domain.vo.VehicleFenceVo;
import com.muyu.vehicle.domain.vo.VehicleIndexVo;
import com.muyu.vehicle.process.SynchronizeVehicleFenceThread;
import com.muyu.vehicle.process.ThreadPool;
import com.muyu.vehicle.utils.PageInfo;
import com.vehicle.common.core.domain.R;
import com.vehicle.common.core.utils.DateUtils;
import com.vehicle.common.core.utils.IdUtils;
import com.vehicle.common.core.utils.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.muyu.vehicle.mapper.VehicleInfoMapper;
import com.muyu.vehicle.domain.VehicleInfo;
import com.muyu.vehicle.service.IVehicleInfoService;

/**
 * 车辆信息Service业务层处理
 *
 * @author muyu
 * @date 2021-09-04
 */
@Service
public class VehicleInfoServiceImpl implements IVehicleInfoService
{
    @Autowired
    private VehicleInfoMapper vehicleInfoMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 查询车辆信息
     *
     * @param id 车辆信息主键
     * @return 车辆信息
     */
    @Override
    public VehicleInfo selectVehicleInfoById(String id)
    {
        return vehicleInfoMapper.selectVehicleInfoById(id);
    }

    /**
     * 查询车辆信息列表
     *
     * @param vehicleInfo 车辆信息
     * @return 车辆信息
     */
    @Override
    public List<VehicleInfo> selectVehicleInfoList(VehicleInfo vehicleInfo)
    {
        return vehicleInfoMapper.selectVehicleInfoList(vehicleInfo);
    }

    /**
     * 新增车辆信息
     *
     * @param vehicleInfo 车辆信息
     * @return 结果
     */
    @Override
    public int insertVehicleInfo(VehicleInfo vehicleInfo)
    {
        vehicleInfo.setCreateTime(DateUtils.getNowDate());
        vehicleInfo.setId(IdUtils.fastSimpleUUID());

        try {
            return vehicleInfoMapper.insertVehicleInfo(vehicleInfo);
        }finally {
            ThreadPool.exeThread(new SynchronizeVehicleFenceThread(redisTemplate,this,vehicleInfo.getVehicleVin()));
        }
    }

    /**
     * 修改车辆信息
     *
     * @param vehicleInfo 车辆信息
     * @return 结果
     */
    @Override
    public int updateVehicleInfo(VehicleInfo vehicleInfo)
    {
        vehicleInfo.setUpdateTime(DateUtils.getNowDate());
        return vehicleInfoMapper.updateVehicleInfo(vehicleInfo);
    }

    /**
     * 批量删除车辆信息
     *
     * @param ids 需要删除的车辆信息主键
     * @return 结果
     */
    @Override
    public int deleteVehicleInfoByIds(String[] ids)
    {
        try {
            return vehicleInfoMapper.deleteVehicleInfoByIds(ids);
        }finally {
            HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
            hashOperations.delete(Config.VEHICLE_FENCE_BIND , ids);
        }
    }

    /**
     * 删除车辆信息信息
     *
     * @param id 车辆信息主键
     * @return 结果
     */
    @Override
    public int deleteVehicleInfoById(String id)
    {
        return vehicleInfoMapper.deleteVehicleInfoById(id);
    }

    @Override
    public void updateVehicleStatusByVin(String vin, Integer status) {
        vehicleInfoMapper.updateVehicleStatusByVin(vin,status);
    }

    @Override
    public List<VehicleFenceVo> selectVehicleFence(String vin) {
        return vehicleInfoMapper.selectVehicleFence(vin);
    }

    @Override
    public VehicleIndexVo getIndexVehicleData() {
        VehicleIndexVo vehicleIndexVo = vehicleInfoMapper.selectIndexVehiceData();
        Set<String> keys = redisTemplate.keys(Config.VEHICLE_CURRENT_LOCATION+"*");
        ValueOperations<String, String> strOperations = redisTemplate.opsForValue();
        for (String key : keys) {
            String value = strOperations.get(key);
            IndexVehicleData indexVehicleData = new IndexVehicleData();
            indexVehicleData.setVin(key.replace(Config.VEHICLE_CURRENT_LOCATION,""));
            indexVehicleData.setPosition(value.split(","));
            vehicleIndexVo.setVehicleDataList(indexVehicleData);
        }
        return vehicleIndexVo;
    }


    @Override
    public R esList(PageInfo pageInfo) {
        // 分页
        Integer pageNum = 0;
        if (pageInfo.getPageNum() >0){
            pageNum = pageInfo.getPageNum()-1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, pageInfo.getPageSize());
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        
        // TermQuery精确查询（车辆VIN完全匹配）
        if (StringUtils.isNotEmpty(pageInfo.getVehicleVin())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("vehicleVin.keyword", pageInfo.getVehicleVin()));
        }

        // MatchQuery全文检索（车辆型号分词匹配）
        if (StringUtils.isNotEmpty(pageInfo.getVehicleVin())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("vehicleVin", pageInfo.getVehicleVin()));
        }

        // BooleanQuery组合条件示例
        if (pageInfo.getStatus() != null) {
            BoolQueryBuilder statusQuery = QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("status", pageInfo.getStatus()))
                .should(QueryBuilders.rangeQuery("mileage").gte(10000));
            boolQueryBuilder.must(statusQuery);
        }

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font style='color:red'>").postTags("</font>").field("vehicleVin");

        //开始查询
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(pageRequest);
        SearchHits<InfoEs> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), InfoEs.class);
        ArrayList<InfoEs> infoEs = new ArrayList<>();
        Long totalHits = searchHits.getTotalHits();
        for (SearchHit<InfoEs> searchHit : searchHits.getSearchHits()) {
            InfoEs infoEs1 = searchHit.getContent();
            //取出高亮
            List<String> vehicleVin = searchHit.getHighlightField("vehicleVin");
            if (vehicleVin != null && vehicleVin.size()>0){
                infoEs1.setVehicleVin(vehicleVin.get(0));
            }
            infoEs.add(infoEs1);
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("total",totalHits);
        map.put("data",infoEs);
        return R.ok(map);
    }
}
